style: Add support for shorthand properties
authorBenjamin Otte <otte@redhat.com>
Sat, 21 May 2011 21:47:19 +0000 (23:47 +0200)
committerBenjamin Otte <otte@redhat.com>
Sat, 21 May 2011 23:25:17 +0000 (01:25 +0200)
Shorthand properties are basically the same a in CSS. For storage in
style properties or the CSS provider, they are unpacked into the real
values, so it is possible to partially override them.

No properties are yet converted to the new world yet, this is just the
code for supporting them.

gtk/gtkcssprovider.c
gtk/gtkstyleproperties.c
gtk/gtkstyleproperty.c
gtk/gtkstylepropertyprivate.h

index 4f09c5e9390c31cc2f7761a4eaa2b7deea69e604..6f8cbe4710576d9f7168fac37d6cb03c933215b6 100644 (file)
@@ -1000,6 +1000,26 @@ gtk_css_ruleset_add (GtkCssRuleset          *ruleset,
                                             NULL,
                                             (GDestroyNotify) property_value_free);
 
+  if (_gtk_style_property_is_shorthand (prop))
+    {
+      GParameter *parameters;
+      guint i, n_parameters;
+
+      parameters = _gtk_style_property_unpack (prop, value, &n_parameters);
+
+      for (i = 0; i < n_parameters; i++)
+        {
+          const GtkStyleProperty *child;
+          GValue *value;
+          
+          child = _gtk_style_property_lookup (parameters[i].name);
+          value = g_memdup (&parameters[i].value, sizeof (GValue));
+          gtk_css_ruleset_add (ruleset, child, value);
+        }
+      g_free (parameters);
+      return;
+    }
+
   ruleset->has_inherit |= gtk_style_param_get_inherit (prop->pspec);
   g_hash_table_insert (ruleset->style, (gpointer) prop, value);
 }
index 1c5f0d95651a14d8e169a280b819447463f3ea0d..a2cb8e53e649d01a8511af48286d29812483a716 100644 (file)
@@ -311,7 +311,9 @@ gtk_style_properties_register_property (GtkStylePropertyParser  parse_func,
   g_return_if_fail (G_IS_PARAM_SPEC (pspec));
 
   _gtk_style_property_register (pspec,
-                                parse_func);
+                                parse_func,
+                                NULL,
+                                NULL);
 }
 
 /**
@@ -511,6 +513,25 @@ _gtk_style_properties_set_property_by_property (GtkStyleProperties     *props,
   else
     g_return_if_fail (style_prop->pspec->value_type == value_type);
 
+  if (_gtk_style_property_is_shorthand (style_prop))
+    {
+      GParameter *parameters;
+      guint i, n_parameters;
+
+      parameters = _gtk_style_property_unpack (style_prop, value, &n_parameters);
+
+      for (i = 0; i < n_parameters; i++)
+        {
+          gtk_style_properties_set_property (props,
+                                             parameters[i].name,
+                                             state,
+                                             &parameters[i].value);
+          g_value_unset (&parameters[i].value);
+        }
+      g_free (parameters);
+      return;
+    }
+
   priv = props->priv;
   prop = g_hash_table_lookup (priv->properties, style_prop->pspec);
 
@@ -789,6 +810,7 @@ lookup_default_value (const GtkStyleProperty *node,
     g_param_value_set_default (node->pspec, value);
 }
 
+/* NB: Will return NULL for shorthands */
 const GValue *
 _gtk_style_properties_peek_property (GtkStyleProperties      *props,
                                      const gchar             *prop_name,
@@ -864,6 +886,8 @@ gtk_style_properties_get_property (GtkStyleProperties *props,
 
   if (val)
     g_value_copy (val, value);
+  else if (_gtk_style_property_is_shorthand (node))
+    _gtk_style_property_pack (node, props, state, value);
   else
     lookup_default_value (node, value);
 
@@ -907,6 +931,15 @@ gtk_style_properties_get_valist (GtkStyleProperties *props,
         {
           G_VALUE_LCOPY (val, args, 0, &error);
         }
+      else if (_gtk_style_property_is_shorthand (node))
+        {
+          GValue packed = { 0 };
+
+          g_value_init (&packed, node->pspec->value_type);
+          _gtk_style_property_pack (node, props, state, &packed);
+          G_VALUE_LCOPY (&packed, args, 0, &error);
+          g_value_unset (&packed);
+        }
       else
         {
           GValue default_value = { 0 };
index 022e57741ad6c19bdaba5cb7d4426f8d0ed9163a..2d6bda681a3d1fd9bde8df4c535fd70fc37ca743 100644 (file)
@@ -1281,6 +1281,41 @@ _gtk_css_value_to_string (const GValue *value)
   return g_strdup_value_contents (value);
 }
 
+gboolean
+_gtk_style_property_is_shorthand  (const GtkStyleProperty *property)
+{
+  g_return_val_if_fail (property != NULL, FALSE);
+
+  return property->pack_func != NULL;
+}
+
+GParameter *
+_gtk_style_property_unpack (const GtkStyleProperty *property,
+                            const GValue           *value,
+                            guint                  *n_params)
+{
+  g_return_val_if_fail (property != NULL, NULL);
+  g_return_val_if_fail (property->unpack_func != NULL, NULL);
+  g_return_val_if_fail (value != NULL, NULL);
+  g_return_val_if_fail (n_params != NULL, NULL);
+
+  return property->unpack_func (value, n_params);
+}
+
+void
+_gtk_style_property_pack (const GtkStyleProperty *property,
+                          GtkStyleProperties     *props,
+                          GtkStateFlags           state,
+                          GValue                 *value)
+{
+  g_return_if_fail (property != NULL);
+  g_return_if_fail (property->pack_func != NULL);
+  g_return_if_fail (GTK_IS_STYLE_PROPERTIES (props));
+  g_return_if_fail (G_IS_VALUE (value));
+
+  property->pack_func (value, props, state);
+}
+
 static void
 gtk_style_property_init (void)
 {
@@ -1392,11 +1427,15 @@ _gtk_style_property_lookup (const char *name)
 
 void
 _gtk_style_property_register (GParamSpec             *pspec,
-                              GtkStylePropertyParser  parse_func)
+                              GtkStylePropertyParser  parse_func,
+                              GtkStyleUnpackFunc      unpack_func,
+                              GtkStylePackFunc        pack_func)
 {
   const GtkStyleProperty *existing;
   GtkStyleProperty *node;
 
+  g_return_if_fail ((pack_func == NULL) == (unpack_func == NULL));
+
   gtk_style_property_init ();
 
   existing = _gtk_style_property_lookup (pspec->name);
@@ -1410,6 +1449,8 @@ _gtk_style_property_register (GParamSpec             *pspec,
   node = g_slice_new0 (GtkStyleProperty);
   node->pspec = pspec;
   node->parse_func = parse_func;
+  node->pack_func = pack_func;
+  node->unpack_func = unpack_func;
 
   g_hash_table_insert (properties, pspec->name, node);
 }
index 57dd0d98df874455307ad47f422d2c34ce19dd2c..38850a19e70b4730ced1f7801cb106b2179681be 100644 (file)
@@ -26,16 +26,35 @@ G_BEGIN_DECLS
 
 typedef struct _GtkStyleProperty GtkStyleProperty;
 
+typedef GParameter *     (* GtkStyleUnpackFunc)            (const GValue           *value,
+                                                            guint                  *n_params);
+typedef void             (* GtkStylePackFunc)              (GValue                 *value,
+                                                            GtkStyleProperties     *props,
+                                                            GtkStateFlags           flags);
+
 struct _GtkStyleProperty
 {
   GParamSpec             *pspec;
   GtkStylePropertyParser  parse_func;
+  GtkStyleUnpackFunc      unpack_func;
+  GtkStylePackFunc        pack_func;
 };
 
-const GtkStyleProperty * _gtk_style_property_lookup        (const char         *name);
+const GtkStyleProperty * _gtk_style_property_lookup        (const char             *name);
 
 void                     _gtk_style_property_register      (GParamSpec             *pspec,
-                                                            GtkStylePropertyParser  parse_func);
+                                                            GtkStylePropertyParser  parse_func,
+                                                            GtkStyleUnpackFunc      unpack_func,
+                                                            GtkStylePackFunc        pack_func);
+
+gboolean                 _gtk_style_property_is_shorthand  (const GtkStyleProperty *property);
+GParameter *             _gtk_style_property_unpack        (const GtkStyleProperty *property,
+                                                            const GValue           *value,
+                                                            guint                  *n_params);
+void                     _gtk_style_property_pack          (const GtkStyleProperty *property,
+                                                            GtkStyleProperties     *props,
+                                                            GtkStateFlags           state,
+                                                            GValue                 *value);
 
 gboolean                _gtk_css_value_parse              (GValue        *value,
                                                            GtkCssParser  *parser,